package com.titanium.java;

import org.junit.Test;

import java.util.*;

/**
 *@program: JavaSenior
 *@description:
 *
 * 一：Map的实现类的结构
 * |-----Map：双列数据：存储key-value对的数据  --类似于高中的函数 y=f(x)
 *      |-----HashMap:作为Map的主要实现类： 线程不安全，效率高；存储null的可以和value
 *          |-----:linkedHashMap: 保证在遍历map元素时，可以按照添加的顺序实现遍历，
 *          原因：在原有的HashMap底层结构上，添加了一对指针，指向前一个和后一个元素
 *          对于频繁的遍历操作，此类执行效率高于HashMap
 *      |-----TreeMap: 保证按照添加的key-value对进行排序，实现排序遍历，此时考虑key的自然排序或者定制排序
 *      |-----Hashtable: 作为古老的实现类：线程安全，效率低；不能存储null的kye和value
 *          |-----properties:c常用来处理配置文件。key和value都是String类型
 *
 *
 *        HashMap的底层：数组+链表 （JDK7之前）
 *                     数组+链表+红黑树（JDK8)
 *
 *         面试题：
 *         1.HashMap的底层实现原理？
 *         2.HashMap和Hashtable的异同?
 *         3.CurrentHashMap和Hashtable的异同?
 *
 *
 *
 *         二：Map结构的理解：
 *         Map中的key：无序，不可重复，使用Set存储所有的key  ---->key所在的类重写equals()和hashCode() 以HashMap为例
 *         Map中的value:无序的，可重复的，使用collection存储所有的value---->value所在的类要重写equals()
 *         一个键值对：key-value构成一个Entry对象。
 *         Map中的entry：无序的、不可重复的、使用Set存储素有的entry
 *
 *
 *         三：HashMap的底层实现原理？
 *         jdk7:
 *         HashMa map = new HashMap();
 *         在实例化以后，底层创建了长度是16的一维素组Entry [] table
 *         ..可能已经执行过多次put...
 *         map.put(key1,value1);
 *         首先，调用key1所在类的hasCode() 计算key1哈希值，此哈希值经过某种算法计算以后，得到entry素组中的存放位置。
 *         如果此位置上的数据为空，key1-value1添加成功.  ---情况1
 *         如果此位置上的数据不为空，（意味着此位置上存在一个或多个数据【已链表形参存在】），比较key1和已经存在的哈希值：
 *          如果key1的哈希值于已经存在的哈希值都不相同，此时key1-value添加成功 --情况2
 *          如果key1的哈希值和已经存在的某一个数据(key2-value2)哈希值相同，继续比较,调用key1所在类的equals()方法比较：
 *              如果equals() 返回false ：此时key1-value添加成功   --情况3
 *              如果equals() 返回true: 使用value1替换value2
 *
 *
 *         补充:关于情况2 和情况3；此时key1-value1和原来的数据以链表方式存储
 *
 *         在不断的添加过程中会涉及到扩容问题，当超出临界值时(且存放的位置非空时) 默认的库容方式：扩容为原来容量的2倍，并将原有的数据复制过来。
 *
 *
 *        jdk8相较于jdk7的底层实现方面不同：
 *        1.new HashMap(); 底层没有创建一个长度为16的数组
 *        2.jdk8底层的数组是：Node []，而非Entry []
 *        3.首次调用put()方法时，底层创建长度为16的数组
 *        4.jdk7底层结构只有数组+链表。 jdk8中底层结构： 数组+链表+红黑树
 *           4.1 形成七上八下（jdk7:新的元素执行旧的元素。jdk8 :就得元素指向新的元素）
 *           4.2 当数组某一个索引位置的元素已链表形式存在的数据个数 > 8 且当前数组长度> 64 时候，此时索引位置上的所有数据改为红黑树存储
 *
 *
 *          DEFAULT_INITIAL_CAPACITY : HashMap的默认容量，16
 *          DEFAULT_LOAD_FACTOR：HashMap的默认加载因子 0.75
 *          threshold：扩容的临界值，=容量*填充因子
 *          TREEIFY_THRESHOLD：Bucket中链表长度大于该默认值，转化为红黑树 8
 *          MIN_TREEIFY_CAPACITY：桶中的Node被树化时最小的hash表容量。64
 *
 *
 *
 *        linkedHashMap的底层实现原理（了解）
 *         源码：
 *          static class Entry<K,V> extends HashMap.Node<K,V> {
 *           Entry<K,V> before, after;   //能够记录添加元素的先后顺序
 *             Entry(int hash, K key, V value, Node<K,V> next) {
 *             super(hash, key, value, next);
 *           }
 *       }
 *
 *
 *      常用方法总结
 *      添加： put(Object keyi,Objet value)
 *      删除： remove(Object key)
 *      修改： put(Object keyi,Objet value) //覆盖
 *      查询： get(Object key)
 *      长度： size()
 *      遍历：keySet() /values() /  entrySet()
 *
 *
 *
 *
 *
 *@author: renfei.huang
 *@create: 2021-10-13 09:02
 */
public class MapTest {






/*        元视图操作的方法：
         Set keySet()：返回所有key构成的Set集合
         Collection values()：返回所有value构成的Collection集合
         Set entrySet()：返回所有key-value对构成的Set集合*/
        @Test
        public  void test5(){

            HashMap map = new HashMap();
            map.put("AA",122);
            map.put(15,342);
            map.put("BB",85);

            //遍历所有的Set keySet()
            Set set = map.keySet();
            Iterator iterator = set.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }

            System.out.println("--------------");

            //遍历所有的 Collection values()
            Collection values = map.values();
            for (Object m: values){
                System.out.println(m);
            }

            System.out.println("----------------");

            //遍历所有的 key-value
            //Set entrySet()
            //方式一： entrySet()
            Set entrySet = map.entrySet();
            Iterator iterator1 = entrySet.iterator();
            while (iterator1.hasNext()){
                Object obj = iterator1.next();

                //entrySet 集合中的元素都是entry
                Map.Entry entry =(Map.Entry)obj;

                System.out.println("key:"+entry.getKey() +",value:"+entry.getValue());
            }

            System.out.println("----------------");

            Set keySet = map.keySet();
            Iterator iterator2 = keySet.iterator();
            while (iterator2.hasNext()){
                Object key = iterator2.next();
                Object value = map.get(key);
                System.out.println("key:"+key +",value:"+value);

            }


        }




/*        元素查询的操作：
         Object get(Object key)：获取指定key对应的value
         boolean containsKey(Object key)：是否包含指定的key
         boolean containsValue(Object value)：是否包含指定的value
         int size()：返回map中key-value对的个数
         boolean isEmpty()：判断当前map是否为空
         boolean equals(Object obj)：判断当前map和参数对象obj是否相等*/
        @Test
        public  void test4(){


            HashMap map = new HashMap();
            map.put("AA",122);
            map.put(15,342);
            map.put("BB",85);
            map.put("CC",85);

            //Object get(Object key)
            System.out.println(map.get("AA"));

            //boolean containsKey(Object key)
            System.out.println(map.containsKey("BB"));

            //boolean containsValue
            System.out.println(map.containsValue(85));

            //int size()
            System.out.println(map.size());

            //boolean isEmpty()
            System.out.println(map.isEmpty());


        }


/*       添加、删除、修改操作：
         Object put(Object key,Object value)：将指定key-value添加到(或修改)当前map对象中
         void putAll(Map m):将m中的所有key-value对存放到当前map中
         Object remove(Object key)：移除指定key的key-value对，并返回value
         void clear()：清空当前map中的所有数据*/
    @Test
    public void test3(){

        HashMap map = new HashMap();
        //添加
        map.put("AA",122);
        map.put(15,342);
        map.put("BB",85);

        //修改
        map.put("AA",95);

        System.out.println(map);

        HashMap map1 = new HashMap();
        map1.put("CC",52);
        map1.put("DD",85);
        map.putAll(map1);
        System.out.println(map);


        //remove(Object key)
        Object value = map.remove("CC");
        System.out.println(value);
        System.out.println(map);

        //clear()
        map.clear(); //与map = null 不同
        System.out.println(map.size());
        System.out.println(map);


    }






    @Test
    public  void test2(){

        LinkedHashMap hashMap = new LinkedHashMap();


//        HashMap hashMap = new HashMap();
        hashMap.put(153,"xfsf");
        hashMap.put(625,"abdfsc");
        hashMap.put(852,"xx");

        System.out.println(hashMap);

    }




    @Test
    public  void  test1(){
        HashMap hashMap = new HashMap();
        hashMap.put("aa",123);
        hashMap.put("aa",456);
        System.out.println(hashMap);

        //不能存null
//        Hashtable hashtable = new Hashtable();
//        hashtable.put(null,123);

    }
}
